package com.betterjr.modules.risk.loanmanage.remote;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

import org.apache.commons.collections.CollectionUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcException;
import com.betterjr.modules.customer.ICustOpenAccountService;
import com.betterjr.modules.customer.entity.CustBaseConfigure;
import com.caucho.hessian.client.HessianProxyFactory;

@Component
public class RomoteUtil {
    private static Logger logger = LoggerFactory.getLogger(RomoteUtil.class);
    private static RomoteUtil romoteUtil;
    // 引用 客户管理-基础配置，根据id 查询
    @Reference(interfaceClass = ICustOpenAccountService.class)
    private ICustOpenAccountService custOpenAccountService;
    // 获取云资金系统的配置接口地址
    // private final static String corpCode = getSysFlag();// 系统标识
    // final static String url = "http://192.168.0.131:8888/cpf/service";//系统服务器地址
    // private final static String url = getInterfaceAddress();
    // final static String url = "http://127.0.0.1/platform/service";
    public static String WSDL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><request><header><reqTime></reqTime><tradeCode></tradeCode><corpCode></corpCode><serialId></serialId></header><body></body></request>";

    @PostConstruct
    public void init() {
        romoteUtil = this;
        romoteUtil.custOpenAccountService = this.custOpenAccountService;
    }

    public static void main(final String[] args) {
        final Map<String, Object> datas = new HashMap<>();
        datas.put("accountCode", "11005577115901");
        // callService(url, "PlanRepaymentCpf", null);
        // callService("QueryCurBalCpf", datas, RomoteUtil.CONSTANT_QUERY_BALANCE_WSDL);
    }

    /** 
     * @Title: callService 
     * @Description: 调用云资金接口
     * @param tradeCode  服务code ，与云资金约定
     * @param datas  map or list 数据
     * @param wsdlStr 何种报文格式，有时间可以去掉，自动根据map 生成
     * @return 返回
     * @throws 
     * @author licz
     * @date 2018年7月3日 下午2:25:25 
     */
    public static Map<String, Object> callService(final Long customerId, final String tradeCode, final Object datas) {
        // customerId即企业客户id ,用来查询客户标识及系统通讯信息
        if (customerId == null || customerId == 0L) {
            logger.error("call 云资金系统异常-----客户id不能为空,customerId:" + customerId);
            throw new RpcException("call 云资金系统异常-----客户id不能为空,customerId:" + customerId);
        }

        final CustBaseConfigure custBaseConfigure = getCustBaseConfigureInfo(customerId, "2");// 2资金管理云平台
        final String corpCode = custBaseConfigure.getSystemIdentifition();// 系统标识 //"bytter_1000"
        final String url = custBaseConfigure.getServicerUrl() + "/cpf/service";// 系统服务器地址
        try {
            if (datas instanceof Map) {
                ((Map) datas).put("customerIdentification", custBaseConfigure.getCustIdentifition());// 客户标识，云资金对接
            }

            // 认证
            System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl");
            final HostnameVerifier hv = new HostnameVerifier() {
                @Override
                public boolean verify(final String urlHostName, final SSLSession session) {
                    return urlHostName.equals(session.getPeerHost());
                }
            };
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
            // 创建HessianProxyFactory实例
            final HessianProxyFactory factory = new HessianProxyFactory();
            // 获得Hessian服务的远程引用

            final String reqData = getReqData(tradeCode, datas, WSDL, corpCode);
            final TransferService ts = (TransferService) factory.create(TransferService.class, url);
            final String result = ts.transfer(corpCode, reqData);
            logger.debug("回应结果：" + result);
            final Map<String, Object> mapResult = new HashMap<>();
            mapResult.put("data", XmlUtil.getDetailList(result));
            mapResult.put("code", XmlUtil.getElNameText(result, "retCode"));
            mapResult.put("message", XmlUtil.getElNameText(result, "retMsg"));
            if (!"0".equals(mapResult.get("code"))) {
                // 处理失败了
                logger.error("云资金处理失败，返回消息：" + mapResult.get("message"));
                throw new RpcException("云资金处理失败，返回消息：" + mapResult.get("message"));
            }
            return mapResult;
        }
        catch (final RpcException e) {
            throw new RpcException("e" + e.getMessage());
        }
        catch (final Exception e) {
            logger.error("call 云资金系统异常", e);
            // TODO 条用计划服务表，写入激活标志是2 ，代表推送异常，TODO 需求类，未明确
            // 直接回滚
            throw new RpcException("call云资金异常：" + e.getMessage());
        }
    }

    /** 
     * @Title: getReqData 
     * @Description: 构造报文
     * @param tradeCode 业务code
     * @param datas
     * @param wsdlStr 
     * @param corpCode 系统标志，企业标识,通讯组织机构code，冗余
     * @return 
     * @throws 
     * @author licz
     * @date 2018年7月4日 下午2:03:10 
     */
    private static String getReqData(final String tradeCode, final Object datas, final String wsdlStr,
            final String corpCode) {
        final SimpleDateFormat formatDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        final SimpleDateFormat formatSerial = new SimpleDateFormat("yyyyMMddhhmmsss");

        final Document doc = XmlUtil.parseXML(wsdlStr);
        final Element root = doc.getRootElement();
        final Element head = root.element("header");

        final Element tradeCodeE = head.element("tradeCode");
        final Element reqTimeE = head.element("reqTime");
        final Element serialIdE = head.element("serialId");
        final Element corpCodeE = head.element("corpCode");

        tradeCodeE.setText(tradeCode);
        reqTimeE.setText(formatDate.format(new Date()));
        serialIdE.setText(formatSerial.format(new Date()));
        corpCodeE.setText(corpCode);

        final Element body = root.element("body");

        if (datas instanceof Map) {
            final Element entity = body.addElement("entity");
            final Map<String, Object> mapDatas = (Map) datas;
            createElements(entity, mapDatas);
        }

        if (datas instanceof List) {
            final List<Map<String, Object>> listDatas = (List) datas;
            for (final Map<String, Object> map : listDatas) {
                final Element listE = body.addElement("list");
                createElements(listE, map);
            }
        }
        return doc.asXML();
    }

    private static void createElements(final Element el, final Map<String, Object> map) {
        Element tmpEl = null;
        for (final String key : map.keySet()) {
            tmpEl = el.addElement(key);
            tmpEl.setText(map.get(key) != null ? map.get(key).toString() : "");
        }
    }

    /** 
     * @Title: getCustBaseConfigureInfo 
     * @Description: 可查询到客户标识 ，及接口地址系统标识
     * @param custNo
     * @param serviceType
     * @return 
     * @throws 
     * @author licz
     * @date 2018年7月5日 下午3:37:30 
     */
    public static CustBaseConfigure getCustBaseConfigureInfo(final Long custNo, final String serviceType) {
        final List<CustBaseConfigure> resultList = romoteUtil.custOpenAccountService.queryCustBaseConfigureInfo(custNo,
                serviceType);
        if (CollectionUtils.isEmpty(resultList)) {
            logger.error("call 云资金系统异常-----queryCustBaseConfigureInfo()查询不到客户配置信息custNo:" + custNo);
            throw new RpcException("call 云资金系统异常-----queryCustBaseConfigureInfo()查询不到客户配置信息custNo:" + custNo);
        }
        return resultList.get(0);
    }
}
